var XMPP_HOST = 'zy48';
var BOSH_SERVICE = 'http://48.lsu.pw:7070/http-bind/';
var WEB_SERVICE = 'http://comm100test.com'
var connection;

var logLevel = 2;

var xmppPres = {};
xmppPres.online = 'online';
xmppPres.offline = 'offline';
xmppPres.waiting = 'waiting';
xmppPres.chating = 'chating';
xmppPres.after = 'after';

var browserType = {};
browserType.chrome = 'chrome';
browserType.firefox = 'firefox';
browserType.opera = 'opera';
browserType.ie = 'ie';
browserType.edge = 'edge';

var systemType = {};
systemType.windows = 'windows';
systemType.linux = 'linux';
systemType.android = 'android';
systemType.ios = 'ios';
systemType.osx = 'osx';

var imageProcessing = false;
var fileProcessing = false;

var peerjs;

/**
 *
 * fullJid: 'lwoefj_lweifj_flweijf_lweifji-custom-dnuvhpj3@zy48/comm100'
 * myJid/bareJid/pureJid: 'lwoefj_lweifj_flweijf_lweifji-custom-dnuvhpj3@zy48'
 * myFullName: 'lwoefj_lweifj_flweijf_lweifji-custom-dnuvhpj3'
 * myName: 'lwoefj_lweifj_flweijf_lweifji'
 * myNick: '张大伟'
 */
var myFullJid;
var myJid;
var myFullName;
var myName;
var myNick;
var myPasswd;
var myPres = {
                show: 'chat', 
                status: {
                        status: xmppPres.waiting,
                        nick: 'nick',
                        browser: browserType.chrome, 
                        system: systemType.windows,
                        viewingUrl: 'http://bing.com',
                        ip: '192.168.1.1',
                        location: '浙江丽水'
                      }
             };

var peerJid;
var peerConnections = {};
var peerFileName;

/**
 * Generate unique id like ->
 *   "bfc7d682_c7f2e1ed_ab0c0193_63b53085"
 *
 * @Source http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript?page=1&tab=votes#answer-105074
 * @return unique id.
 */
function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
  }

  return s4() + s4() + '_' + s4() + s4() + '_' +
      s4() + s4() + '_' + s4() + s4();
};

function consoleLog(mess, level) {
  if (level <= logLevel) {
    console.log('log level ' + level + ': ' + mess);
  }
}


function preventDefault(evt){
  evt.preventDefault();
  evt.stopPropagation();
}

function checkWebrtcSupport() {
  if(navigator.userAgent.search('Chrome') >= 0) {
    webrtcSupport = true;
  } else {
    webrtcSupport = false;
  }
}

function replaceQuoteInString(s) {
  while(s.search('&quot;') >= 0) { s = s.replace('&quot;', '"');}
}

/**
 *
 * trans raw text message like 
 *    'alifewjfverio[emoji_12]lseia sliefj[emoji_3]' 
 * to message contain emoji like 
 *    'alifewjfverio<img class="emoji-message" src="./emoji/qq/12.gif">lseia sliefj<img class="emoji-message" src="./emoji/qq/3.gif">'
 *
 */
function transTextMessage(content) {
  while(content.search('\\[emoji_\\d+]') >= 0) {
    var emoji = /\[emoji_\d+]/.exec(content);
    var substitute = /\d+/.exec(emoji);
    substitute = '<img class="emoji-message" src="/emoji/qq/' + substitute + '.gif">';
    content = content.replace(emoji, substitute);
  }
  return content;
}


/************************************************************************************************************
 * 
 * file functions.
 *
 ***********************************************************************************************************/


var tmpDataUrl;
var fileDataUrlReader = new FileReader();
fileDataUrlReader.onload = function (fileReaderEvent) {
  tmpDataUrl = fileReaderEvent.target.result;
};

function setBlobToImgType(blob) {
  blob = new Blob([blob],{type : 'image/jpeg'})
  return blob;
}


function setBlobToFileName(blob, fileName) {
  var file = new File([blob], fileName)
  return file;
}

function getDataUrlOfFile(file) {
  fileDataUrlReader.readAsDataURL(file);
  return tmpDataUrl;
}


/***********************************************************************************************************************
 *
 * DOM functions.
 *
 **********************************************************************************************************************/

function generateEmojiItems() {
  var ul = $('#emoji-box');
  for(i = 1; i < 76; i++) {
    var li = document.createElement('li');
    $(li).attr('class', 'emoji-grid-cell');
    $(li).html('<img class="emoji-image" src="/emoji/qq/' + i + '.gif">');
    $(ul).append(li);
  }
}

function playMessageRingtone() {
  $('.on-message-audio')[0].play();
}

function openChatpanel() {
  $('.chat-panel-title').html('客服-' + getServiceName(peerJid));
  $('.chat_panel').show('drop');
};

function hideChatPanel() {
  $('.chat_panel').hide();
};

function showBeginChatPrompt() {
  $('#begin_chat_prompt').show();
};

function hideBeginChatPrompt() {
  $('#begin_chat_prompt').hide();
};

function messageBoardScrollToBottom(messageBoard) {
  if(!messageBoard) {
    messageBoard = $('.chat_panel_message_board');
  }
  $(messageBoard).animate({scrollTop: $(messageBoard)[0].scrollHeight}, 100);
}

function showImageViewerLayer() {
  $('.img-viewer-layer').show();
}

function hideImageViewerLayer() {
  $('.img-viewer-layer').hide();
}

function appendSystemMessage(message) {
  var dom = document.createElement('div');
  $(dom).attr('class', 'system-message');
  $(dom).html('<span class="system-message-text">' + message + '</span>');
  $('.chat_panel_message_board').append(dom);
}

/**
 * Show text message on chat board.
 *
 * @param messageSource the sender of the message, 1 for peer, 2 for self. TODO: 3 for notify.
 */
function appendTextMessage(messageSource, textMessage) {
  var container = document.createElement('div');
  var paragraph = document.createElement('p');
  textMessage = transTextMessage(textMessage);
  paragraph.innerHTML = textMessage;
  $(container).append(paragraph);
  if (messageSource == 1) {
    $(container).addClass("chat_message_in");
  } else if (messageSource == 2) {
    $(container).addClass("chat_message_out");
  }
  $('.chat_panel_message_board').append(container);
  messageBoardScrollToBottom($('.chat_panel_message_board'));
}

/**
 * @param messageSource the sender of the message, 1 for peer, 2 for self. TODO: 3 for notify.
 */
function appendImageMessage(messageSource, blobUrl) {
  var container = document.createElement('div');
  var paragraph = document.createElement('p');
  paragraph.innerHTML = '<img class="chat-image" src="' + blobUrl + '">';
  $(container).append(paragraph);
  if (messageSource == 1) {
    $(container).addClass("chat_message_in");
  } else if (messageSource == 2) {
    $(container).addClass("chat_message_out");
  }
  $('.chat_panel_message_board').append(container);
  messageBoardScrollToBottom($('.chat_panel_message_board'));
}

function appendFileMessage(messageSource, blobUrl) {
  var container = document.createElement('div');
  var paragraph = document.createElement('p');
  var download = 'download';
  if(peerFileName) {
    consoleLog('peerFileName set to ' + peerFileName);
    download += '=' + peerFileName;
  }
  paragraph.innerHTML = '<a class="file-download-button" href="' 
                       + blobUrl 
                       + '" ' + download + '><i class="iconfont">&#xe61c;<span class="file-message-download-tip">点击下载文件</span> </i></a>';
  $(container).append(paragraph);
  if (messageSource == 1) {
    $(container).addClass("chat_message_in");
  } else if (messageSource == 2) {
    $(container).addClass("chat_message_out");
  }
  $('.chat_panel_message_board').append(container);
  messageBoardScrollToBottom($('.chat_panel_message_board'));
}


/***********************************************************************************************************************
 *
 * ajax functions.
 *
 **********************************************************************************************************************/

function  submitCustomInfo(nick, email, phone, message) {
  if(!nick) {nick = myFullName};
  $.get('/custom/submitInfo', {name: myFullName, nick: nick, email: email, phone: phone, message: message}, function(data, status) {

  });
}

/***********************************************************************************************************************
 *
 * XMPP functions.
 *
 **********************************************************************************************************************/


function checkIfRosterIsService(rosterItem) {
  if(rosterItem.jid.search('-service-') >= 0) {
    return true;
  }
  return false;
}

function checkIfRosterOnline(rosterItem) {
  var resources = rosterItem.resources;
  for(i in resources) {
    if(resources[i].show == 'chat') {
      return true;
    }
  }
  return false;
}


function checkIfRosterFree(rosterItem) {
  var resources = rosterItem.resources;
  for(i in resources) {
    var status = resources[i].status;
    if(status == 'online') {
      return true;
    }
  }
  return false;
}


function getBareJid(fullJid) {
  var idx = fullJid.search('/');
  if (idx >= 0) {
    fullJid = fullJid.substr(0, idx);
  }
  return fullJid;
}


function getFullName(jid) {
  var idx = jid.search('@');
  if(idx >= 0) {
    jid = jid.substr(0, idx);
  }
  return jid;
}

function getServiceName(serviceJid) {
  if(!serviceJid) return serviceJid;
  var idx = serviceJid.search('-service-');
  if(idx >= 0) {
    serviceJid = serviceJid.substr(0, idx);
  }
  return serviceJid;
}

function initMyPres() {
  myPres.show = 'chat';
  consoleLog('initing mypres', 1);
  var myStatus = myPres.status;
  myStatus.status = xmppPres.waiting;
  myStatus.nick = myNick;
  if(navigator.userAgent.search('chrome') >= 0) {
    myStatus.browser = browserType.chrome;
  } else if(navigator.userAgent.search('firefox') >= 0) {
    myStatus.browser = browserType.firefox;
  } else if(navigator.userAgent.search('edge') >= 0) {
    myStatus.browser = browserType.edge;
  } else if(navigator.userAgent.search('opera') >= 0) {
    myStatus.browser = browserType.opera;
  }
  consoleLog('inited browser type', 1);

  if(navigator.userAgent.search('Windows') >= 0) {
    myStatus.system = systemType.windows;
  } else if(navigator.userAgent.search('Android') >= 0) {
    myStatus.system = systemType.android;
  } else if(navigator.userAgent.search('IOS') >= 0) {
    myStatus.system = systemType.ios;
  }

/*  myStatus.viewingUrl = (window.location != window.parent.location)
            ? document.referrer
            : document.location;;*/
  myStatus.viewingUrl = document.referrer;
  myStatus.ip = returnCitySN.cip;
  myStatus.location = returnCitySN.cname;
  consoleLog('init myPres', 1);
}



function sendPresSchedule() {
  sendPresence();
  setTimeout("sendPresSchedule()", 10000);
}

/**
 * Send a text chat message to Someone.
 */
function sendChatMessage(receiverJid, textMessage) {
  connection.send($msg({to: receiverJid, type: 'chat'})
      .cnode(Strophe.xmlElement('body', textMessage))
      .tree());
};


function askSubscribe(pureJid) {
  consoleLog('ask subscribe to ' + pureJid, 1);
  connection.send($pres({to: pureJid, type: 'subscribe'}).tree());
  subscribedTo(pureJid);
}

function subscribedTo(pureJid) {
  consoleLog('subscribed to ' + pureJid);
  connection.send($pres({to: pureJid, type: 'subscribed'}).tree());
}

function pickUp(serviceJid) {
  connection.send($msg({to: serviceJid, type: 'hello'}).tree());
}

function transmitTo(serviceJid) {
  var lastServiceJid = peerJid;
  peerJid = serviceJid;
  connection.send($msg({to: peerJid, from: myJid, type: 'transmit'})
      .cnode(Strophe.xmlElement('body', lastServiceJid))
      .tree());
  appendSystemMessage('转接到客服 ' + getServiceName(serviceJid));

}

function sendPresence() {
  consoleLog('send pres to all.');
  var myStatus = myPres.status;
  /*connection.send($pres()
    .c('show', myPres.show).up()
    .c('status', 
       {}, 
       '{"name":"' + myStatus.nick + '",'
       + '"browser":"' + myStatus.browser + '",'
       + '"system":"' + myStatus.system + '",'
       + '"ip":"' + myStatus.ip + '",'
       + '"location":"' + myStatus.location + '",'
       + '"viewingUrl":"' + myStatus.viewingUrl + '"'
       + '}').tree());*/
if(!myStatus.viewingUrl) {
  myStatus.viewingUrl = "http://comm100test.com";
}
       connection.send($pres()
    .c('show', myPres.show).up()
    .c('status')
      .c('status', myStatus.status).up()
      .c('nick', myStatus.nick).up()
      .c('browser', myStatus.browser).up()
      .c('system', myStatus.system).up()
      .c('ip', myStatus.ip).up()
      .c('location', myStatus.location).up()
      .c('viewingUrl', myStatus.viewingUrl).tree());
}

function onSearchResult(iq) {
  consoleLog('on search result');
  var items = iq.getElementsByTagName('item');
  for (i = 0; i < items.length; i++) {
    var item = items[i];
    var fields = item.getElementsByTagName('field');
    for (j = 0; j < fields.length; j++) {
      var field = fields[j];
      if (field.getAttribute('var') == 'jid') {
        var value = field.getElementsByTagName('value');
        var jid = Strophe.getText(value[0]);
        consoleLog('searched: ' + jid, 1);
        askSubscribe(getBareJid(jid));
      }
    }
  }
}

function onIq(iq) {
  var type = iq.getAttribute('type');
  var from = iq.getAttribute('from');
  consoleLog('on iq from ' + from + ', type ' + type, 1);
  if (from == 'search.' + XMPP_HOST && type == 'result') {
    onSearchResult(iq);
  }
  return true;
}

function onGetRoster(items) {
  if (!items) {
    return;
  }
  consoleLog('get roster items ' + items.length, 1);
}

function onMessage(msg) {
  var from = msg.getAttribute('from');
  var type = msg.getAttribute('type');
  consoleLog('on message from ' + from + ', type ' + type, 1);

  if(type == 'hello') {
    peerJid = getBareJid(from);
    showBeginChatPrompt();
    myPres.status.status = xmppPres.chating;
    sendPresence();
    return true;
  }
  var elems = msg.getElementsByTagName('body');

  hideBeginChatPrompt();
  if(type == 'transmit') {
    consoleLog('on transmit', 2);
    var serviceJid = Strophe.getText(msg.getElementsByTagName('body')[0]);
    transmitTo(serviceJid);
    return true;
  }
  if (type == 'chat' && elems.length > 0) {
    playMessageRingtone();
    hideBeginChatPrompt();
    openChatpanel();
    appendTextMessage(1, Strophe.getText(msg.getElementsByTagName('body')[0]));
    return true;
  }
  if(type == "fileName") {
    peerFileName = Strophe.getText(msg.getElementsByTagName('body')[0]);
  }
  
  return true;
}

function onPresence(pres) {
  var presType = pres.getAttribute('type');
  var from = pres.getAttribute('from');
  consoleLog('on pres: from ' + from + ', type ' + presType, 1);
  if (presType == 'subscribe') {
    onSubscribe(pres);
    return true;
  }
  if(presType == 'unavailable') {
    from = getBareJid(from);
    if(from == peerJid);
//    appendSystemMessage('客服已离开');
 //   appendSystemMessage('你可以在右上角留言或评分');
    return true;
  }
  return true;
}


function onConnect(status) {
  if (status === Strophe.Status.REGISTER) {
    connection.register.fields.username = myFullName;
    connection.register.fields.password = myPasswd;
    consoleLog('register with ' + myName + ', ' + myPasswd);
    connection.register.submit();
  } else if (status === Strophe.Status.REGISTERED) {
    consoleLog("registered!");
    connection.authenticate();
  } else if (status === Strophe.Status.CONFLICT) {
    consoleLog("Contact already existed!");
  } else if (status === Strophe.Status.NOTACCEPTABLE) {
    consoleLog("Registration form not properly filled out.")
  } else if (status === Strophe.Status.REGIFAIL) {
    consoleLog("The Server does not support In-Band Registration")
  } else if (status == Strophe.Status.CONNECTING) {
    consoleLog('Strophe is connecting.', 1);
  } else if (status == Strophe.Status.CONNFAIL) {
    consoleLog('Strophe failed to connect.', 1);
    $('#connect').get(0).value = 'connect';
  } else if (status == Strophe.Status.DISCONNECTING) {
    consoleLog('Strophe is disconnecting.', 1);
  } else if (status == Strophe.Status.DISCONNECTED) {
    consoleLog('Strophe is disconnected.', 1);
    $('#connect').get(0).value = 'connect';
  } else if (status == Strophe.Status.CONNECTED) {
    consoleLog('Strophe is connected.', 1);
    connection.addHandler(onIq, null, 'iq', 'result', null, null);
    consoleLog('iq handler added', 1);
    connection.addHandler(onMessage, null, 'message', null, null, null);
    consoleLog('message handler added', 1);
    connection.addHandler(onPresence, null, 'presence');
    consoleLog('presence handler added.', 1);
    initMyPres();
    consoleLog('mypres inited', 1);
    sendPresence();
    sendPresSchedule();
    searchService();
    buildPeerjs();
    connection.roster.get(onGetRoster, 0);
    showBeginChatPrompt();
  }
}


function searchService() {
  connection.send($iq({'type': 'set', 'to': 'search.' + XMPP_HOST})
      .cnode(Strophe.xmlElement('query', {'xmlns': 'jabber:iq:search'}))
      .cnode(Strophe.xmlElement('x', {'xmlns': 'jabber:x:data', 'type': 'submit'}))
      .cnode(Strophe.xmlElement('field', {'var': 'FORM_TYPE', type: 'hidden'}))
      .cnode(Strophe.xmlElement('value', 'jabber:iq:search')).up().up()
      .cnode(Strophe.xmlElement('field', {var: 'search'}))
      .cnode(Strophe.xmlElement('value', '-service-' + siteCode))
      .up().up().cnode(Strophe.xmlElement('field', {'var': 'Email'}))
      .cnode(Strophe.xmlElement('value', '1'))
      .up().up().cnode(Strophe.xmlElement('field', {'var': 'Username'}))
      .cnode(Strophe.xmlElement('value', '1'))
      .up().up().cnode(Strophe.xmlElement('field', {'var': 'Name'}))
      .cnode(Strophe.xmlElement('value', '1'))
      .tree());
}

function login() {
  connection.connect(myJid, myPasswd, onConnect);
}


/*************************************************************************************************************
 *
 * peerjs functions.
 *
 ************************************************************************************************************/

var dataView;
var dataBlob;
var dataUrl;

function onPeerjsConnect(conn) {
  consoleLog('on peerjs connect', 2);
  if (conn.label === 'img') {
    consoleLog('on img connect from ' + conn.peer, 2);
    imgConnectionValid(conn.peer);
    peerConnections[conn.peer]['imgConnection'];
    peerConnections[conn.peer]['imgConnection'] = conn;
    conn.on('data', function(data) {
      consoleLog('on img in connect with ' + conn.peer, 2);
      if (data.constructor === ArrayBuffer) {
        dataView = new Uint8Array(data);
        dataBlob = new Blob([dataView]);
        dataBlob = setBlobToImgType(dataBlob);
        dataUrl = window.URL.createObjectURL(dataBlob);
        appendImageMessage(1, dataUrl)
      }
    });
  } else if(conn.label == 'file') {
    consoleLog('on file connect from ' + conn.peer, 1);
    fileConnectionValid(conn.peer);
    peerConnections[conn.peer]['fileConnection'];
    peerConnections[conn.peer]['fileConnection'] = conn;
    conn.on('data', function(data) {
      consoleLog('on file in connect with ' + conn.peer, 1);
      if (data.constructor === ArrayBuffer) {
        dataView = new Uint8Array(data);
        dataBlob = new Blob([dataView]);
        dataUrl = window.URL.createObjectURL(dataBlob);
        appendFileMessage(1, dataUrl, $('#' + conn.peer + '-custom-panel'));
      }
    });
  }
}


  var myImgFile;
  var myFile;
  var peerjsConn;

  function sendImg() {
    var peerName = getFullName(peerJid);
    consoleLog('send img file to ' + peerName, 1);
    peerConnections[peerName]['imgConnection'].send(myImgFile);
  }

  function sendFile() {
    var peerName = getFullName(peerJid);
    consoleLog('send file to ' + peerName, 1);
    peerConnections[peerName]['fileConnection'].send(myFile);
  }

function peerJsImgConnectTo(peerId) {
  var conn = peerjs.connect(peerId, { label: 'img', reliable: true });
  conn.on('open', function() {
    consoleLog('img connection with ' + peerId + ' opened');
    onPeerjsConnect(conn);
  });
  conn.on('close', function() {
    consoleLog('img connect with ' + peerId + ' disconnected');
  });
  conn.on('error', function(err) { consoleLog(err, 2); });
}

function peerJsFileConnectTo(peerId) {
  var conn = peerjs.connect(peerId, { label: 'file', reliable: true });
  conn.on('open', function() {
    onPeerjsConnect(conn);
    peerConnections[getFullName(peerJid)]['fileConnection'];
    peerConnections[getFullName(peerJid)]['fileConnection'] = conn;
  });
  conn.on('error', function(err) { consoleLog(err, 2); });
  conn.on('close', function() {
    consoleLog('file connect with ' + peerId + ' of file ' + fileName + ' disconnected');
  });
}

function imgConnectionValid(peerName) {
  if(!peerConnections[peerName]) {
    peerConnections[peerName] = {};
    return false;
  }
  if(!peerConnections[peerName]['imgConnection']) {
    return false;
  }
  if(!peerConnections[peerName]['imgConnection'].open) {
    return false;
  }
  return true;
}

function fileConnectionValid(peerName) {
  if(!peerConnections[peerName]) {
    peerConnections[peerName] = {};
    return false;
  }
  if(!peerConnections[peerName]['fileConnection']) {
    return false;
  }
  if(!peerConnections[peerName]['fileConnection'].open) {
    return false;
  }
  return true;
}

function buildConnectionsTo(peerName) {
  if(!imgConnectionValid(peerName)) {
    peerJsImgConnectTo(peerName);
  }
  if(!fileConnectionValid(peerName)) {
    peerJsFileConnectTo(peerName);
  }
}

function buildPeerjs() {
  if(webrtcSupport) {
    peerjs = new Peer(myFullName, {
      // Set API key for cloud server (you don't need this if you're running your
      // own.
      key: 'x7fwx2kavpy6tj4i',

      // Set highest debug level (log everything!).
      debug: 3,

      // Set a logging function:
      logFunction: function() {
        var copy = Array.prototype.slice.call(arguments).join(' ');
        consoleLog(copy, 2);
      }
    });

    // Show this peer's ID.
    peerjs.on('open', function(id){
      consoleLog('peer on open, id: ' + id, 2);
    });

    peerjs.on('error', function(err) {
      consoleLog(err, 2);
    });

    peerjs.on('connection', onPeerjsConnect);
  }
}



$(document).ready(function () {

  consoleLog('document init...............................................', 1);
  generateEmojiItems();

//  $('.chat_panel').draggable();

  if(logLevel >= 3) {
    $('#logbox').show();
  }

  siteCode = new RegExp(".{8}\$").exec(location.pathname)[0];
  $('.begin-chat-prompt-img').attr('src', 'http://comm100.lsu.pw/sideImage/' + siteCode);
  connection = new Strophe.Connection(BOSH_SERVICE);
  connection.rawInput = function (data) {
    $('#logbox').append('<div></div>').append(document.createTextNode('recv: ' + data));
  };
  connection.rawOutput = function (data) {
    $('#logbox').append('<div></div>').append(document.createTextNode('send: ' + data));
  };
  myPasswd = localStorage.getItem('myPasswd');
  myNick = localStorage.getItem('myNick');
  myFullName = localStorage.getItem('myName-' + siteCode);
  if (!myFullName) {
    myFullName = guid() + '-custom-' + siteCode;
    localStorage.setItem('myName-' + siteCode, myFullName);
    myJid = myFullName + '@' + XMPP_HOST;
    if (!myPasswd) {
      myPasswd = guid();
      localStorage.setItem('myPasswd', myPasswd);
    }
    if(!myNick) {
      myNick = myFullName;
    }
    connection.register.connect(XMPP_HOST, onConnect);
  } else {
    myJid = myFullName + '@' + XMPP_HOST;
    if(!myNick) {
      myNick = myFullName;
    }
    login();
  }

  $('body').on('click', '#begin_chat_button', function () {
    consoleLog('begin chat button clicked', 1);
    myPres.status.status = xmppPres.chating;
    sendPresence();
    if(peerJid) {
      hideBeginChatPrompt();
      openChatpanel();
      appendSystemMessage('正在与客服聊天');
    } else {
      for(i = 0; i < connection.roster.items.length; i++) {
        var rosterItem = connection.roster.items[i];
        consoleLog('check item ' + rosterItem.jid);
        if(checkIfRosterIsService(rosterItem) && checkIfRosterOnline(rosterItem) && checkIfRosterFree(rosterItem)) {
          peerJid = rosterItem.jid;
          pickUp(peerJid);
          hideBeginChatPrompt();
          openChatpanel();
          appendSystemMessage('正在与客服聊天');
          return;
        }
      }
      consoleLog('no service online.', 1);
      var rosterItem = Math.floor(Math.random() * 10000) % connection.roster.items.length;
      rosterItem = connection.roster.items[rosterItem];
      if(!rosterItem) {
        openChatpanel();
        appendSystemMessage('无客服在线');
        appendSystemMessage('如需帮助，点击右上角留下您的联系方式');
        hideBeginChatPrompt();
        return;
      }
      peerJid = rosterItem.jid;
      hideBeginChatPrompt();
      openChatpanel();
      appendSystemMessage('无客服在线，您可以发送离线消息');
      appendSystemMessage('如需帮助，点击右上角留下您的联系方式');
    }
  });

  $('body').on('click', '.close-chat-panle-button', function () {
    hideChatPanel();
    myPres.status.status = xmppPres.after;
    sendPresence();
    showBeginChatPrompt();
  });

  $('body').on('keypress', '.chat_panel_send_board_input', function (event) {
    if (event.keyCode == 13) {
      $('.send-button').click();
    }
  });

  $('body').on('click', '.send-button', function () {
    var message = $('.chat_panel_send_board_input').val();
    if(!message) return;
    sendChatMessage(peerJid, message);
    appendTextMessage(2, message);
    $('.chat_panel_send_board_input').val("");
  });

 
  $('body').on('click', '.add-image-button', function () {
    if(imageProcessing) {
      imageProcessing = false; 
      return;
    } else {
      imageProcessing = true;
    }
    consoleLog('img-button clicked', 1);
    $('#img-input').click();
  }); 

  $('body').on('click', '.add-file-button', function () {
    consoleLog('img-button clicked', 1);
    $('#file-input').click();
  }); 


  $('body').on('click', '.chat-image', function () {
    var imgUrl = $(this).attr('src');
    $('.img-show').attr('src', imgUrl);
    showImageViewerLayer();
  });


  $('body').on('click', '.img-viewer-close-button', function () {
    hideImageViewerLayer();
  });

function addEmojiButtonClick(event) {
     consoleLog('add emoji button clicked', 1);
    var emojiBoxX = $('.chat_panel')[0].offsetLeft + $('.add-emoji-button')[0].offsetLeft - 120;
    var emojiBoxY = $('.chat_panel')[0].offsetTop + $('.add-emoji-button')[0].offsetTop - 240;
    var emojiBox = $('#emoji-box');
    emojiBox.css('left', emojiBoxX);
    emojiBox.css('top', emojiBoxY);
    $('#emoji-box').show();
  }

  $('body').on('hover', '.add-emoji-button', addEmojiButtonClick);

  $('body').on('mouseleave', '#emoji-box', function() {
    $('#emoji-box').hide();
  });

  $('body').on('click', ".emoji-grid-cell", function() {
    $('#emoji-box').hide();
    var inputText = $('.text-input').val();
    var emojiText = '[emoji_' + /\d+/.exec($(this).children('.emoji-image').attr('src')) + ']';
    $('.text-input').val(inputText + emojiText);
  });

  $('body').on('click', '.edit-info-button', function() {
    consoleLog('edit info button clicked', 1);
    var boardPositionX = $('.chat_panel')[0].offsetLeft + $(this)[0].offsetLeft - 240;
    var boardPositionY = $('.chat_panel')[0].offsetTop + $(this)[0].offsetTop + 30;
    $('#personal-info-edit-board').css('left', boardPositionX);
    $('#personal-info-edit-board').css('top', boardPositionY);
    $('#personal-info-edit-board').show();
  });

  $('body').on('click', '.personal-info-submit-button', function() {
    var nick = $('.personal-name-input').val();
    $('.personal-name-input').val('');
    var email = $('.personal-email-input').val();
    $('.personal-email-input').val('');
    var phone = $('.personal-phone-input').val();
    $('.personal-phone-input').val('');
    var message = $('.personal-message-input').val();
    $('.personal-message-input').val('');
    $('#personal-info-edit-board').hide('highlight');
    nick = nick.trim();
    if(nick != '') {
      myPres.status.nick = nick;
      sendPresence();
    }
    submitCustomInfo(nick, email, phone, message);
  });


  $('body').on('change', '#img-input', function () {
    var peerName = getFullName(peerJid);
    myImgFile = $('#img-input')[0].files;
    if(myImgFile.length > 0) {
      myImgFile = myImgFile[0];
      appendImageMessage(2, window.URL.createObjectURL(myImgFile));
      if(!imgConnectionValid(peerName)) {
        buildConnectionsTo(peerName);
        setTimeout('sendImg()', 1500);
      } else {
        sendImg();
      }
    }
    $(this).val('');
    imageProcessing = false;
  });

  $('body').on('hover', '.star-item', function() {
    var idx = $(this).attr('order');
    consoleLog('hover on star ' + idx, 3);
    for(i = 0; i <= idx; i++) {
      var starItem = $('.star-item')[i];
      $(starItem).attr('class', 'star-item active iconfont');
    }
    for(; i < 5; i++) {
      var starItem = $('.star-item')[i];
      $(starItem).attr('class', 'star-item iconfont');
    }
  });

  $('body').on('change', '#file-input', function() {
    var peerName = getFullName(peerJid);
    myFile = $('#file-input')[0].files;
    if(myFile.length > 0) {
      myFile = myFile[0];
      connection.send($msg({to: peerName + '@' + XMPP_HOST, type: 'fileName'})
      .cnode(Strophe.xmlElement('body', myFile.name))
      .tree());
      appendSystemMessage('你已发送一个文件');
      if(!fileConnectionValid(peerName)) {
        buildConnectionsTo(peerName);
        setTimeout('sendFile()', 1500);
      } else {
        setTimeout('sendFile()', 500);
      }
    }
    $(this).val('');
  });

  $('body').on('click', '.star-submit-button', function() {
    consoleLog('star submit button clicked', 2);
    var idx = 0;
    for(i = 0; i < 5; i++) {
      var starItem = $('.star-item')[i];
      if(!$(starItem).hasClass('active')) {
        break;
      }
      idx = i + 1;
    }
    consoleLog('submit star ' + idx, 1);
    $.get(WEB_SERVICE + '/custom/star', {customName: myFullName, star: idx});
    $('#star-service-container').hide();
  });
  
  $('body').on('click', '.rate-button', function() {
    var boardPositionX = $('.chat_panel')[0].offsetLeft + $(this)[0].offsetLeft - 140;
    var boardPositionY = $('.chat_panel')[0].offsetTop + $(this)[0].offsetTop + 30;
    $('#star-service-container').css('left', boardPositionX);
    $('#star-service-container').css('top', boardPositionY);
    $('#star-service-container').show();
  });

  checkWebrtcSupport();

  window.onunload = window.onbeforeunload = function(e) {
    connection.disconnect();
    peerjs.disconnect();
    if (!!peer && !peer.destroyed) {
      peer.destroy();
    }
  };

});
